package Modele;

/**
 * Classe IO qui permet de lire/ecrire sur les fichiers TSP
 * @author kami
 */
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;

public class TSPLib_Data {

    /*===========================================================================================*/

    // Nombre de sommets
    private int nbrSommets;

    // Distances entre les sommets tel que defini dans la TSPLIB
    private float[][] matriceDistance;

    // Distance entre les sommets du cycles
    private int[][] cycleDistance;

    // Matrice des coûts d'assignement
    private int[][] coutAssignement;


    /*===========================================================================================*/
    /**
     * Constructeur
     */
    public TSPLib_Data() {
    }

    /*===========================================================================================*/
    /**
     *  Lecture des donn�es du TSP dans un fichier et affectation des valeurs
     *  @param tspFile : le fichier source
     */
    public void read(String tspFile) {
        int val, i, j;
        String s;

        try {
            BufferedReader fReader;
            fReader = new BufferedReader(new FileReader(tspFile));

            s = fReader.readLine();
            System.out.println(s);
            s = fReader.readLine();
            System.out.println(s);
            s = fReader.readLine();
            System.out.println(s);

            s = fReader.readLine();
            s = s.substring(12, s.length());
            nbrSommets = Integer.parseInt(s);
            //System.out.println("DIMENSION : " + nbrSommets);

            s = fReader.readLine();
            System.out.println(s);
            s = fReader.readLine();
            System.out.println(s);

            // On dimensionne nos tableaux à la bonne taille
            matriceDistance = new float[nbrSommets][nbrSommets];
            // Tableaux des coordonnees des points
            float[] x = new float[nbrSommets];
            float[] y = new float[nbrSommets];

            // Affectation des valeurs dans les tableaux
            StringTokenizer st;
            for (i = 0; i < nbrSommets; i++) {
                st = new StringTokenizer(fReader.readLine());
                val = Integer.parseInt(st.nextToken());
                x[i] = Float.parseFloat(st.nextToken());
                y[i] = Float.parseFloat(st.nextToken());
                //System.out.println(val + " " + x[i] + " " + y[i]);
            }

            // Fermeture du fichier
            fReader.close();

            // Mise à 0 des distances lorsque source = destination
            for (i = 0; i < nbrSommets; i++) {
                matriceDistance[i][i] = 0;
            }

            // Affectation des distances
            for (i = 0; i < nbrSommets - 1; i++) {
                for (j = i + 1; j < nbrSommets; j++) {
                    matriceDistance[i][j] = (float) (Math.sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]))+0.5);
                    matriceDistance[j][i] = matriceDistance[i][j];
                    }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Fonction qui permet de générer la matrice des coûts
     * @param alpha :
     */
    public void creerInstanceRSP(int alpha) {
        int i, j;

        // On dimensionne nos tableaux a la bonne taille
        cycleDistance = new int[nbrSommets][nbrSommets];
        coutAssignement = new int[nbrSommets][nbrSommets];

        // Assignation des coûts
        for (i = 0; i < nbrSommets; i++) {
            for (j = 0; j < nbrSommets; j++) {
                cycleDistance[i][j] = (int) (alpha * getDistance(i, j));
                cycleDistance[j][i]=cycleDistance[i][j];
                coutAssignement[i][j] = (int) ((10 - alpha) * getDistance(i, j));
                coutAssignement[j][i]=coutAssignement[i][j];
            }
        }
    }


    /*===========================================================================================*/
    /**
     * Retourne la valeur de la matriceDistance entre deux points
     * @param x : premier point
     * @param y : deuxième point
     * @return : la valeur de la matriceDistance entre les deux points
     */
    public float getDistance(int x, int y) {
        return matriceDistance[x][y];
    }

    /**
     * Affecte une valeur dans le tableau des distances entre deux points
     * @param matriceDistance : valeur de la matriceDistance entre les deux points
     * @param x : premier point
     * @param y : deuxi�me point
     */
    public void setDistance(float distance, int x, int y) {
        this.matriceDistance[x][y] = distance;
    }

    /**
     * Retourne le nombre de sommets du probl�me
     * @return : le nombre de sommets
     */
    public int getNbrSommets() {
        return nbrSommets;
    }

    /**
     * Affecte la valeur du nombre de sommets du probleme
     * @param nbn : nombre de sommets
     */
    public void setNbrSommets(int nbSommets) {
        this.nbrSommets = nbSommets;
    }

    /**
     * Retourne le cout d'assignement entre deux points
     * @param x : premier point
     * @param y : deuxième point
     * @return : le cout d'assignement entre ces deux points
     */
    public int getCoutAssignement(int x, int y) {
        return coutAssignement[x][y];
    }

    /**
     * Affecte le cout d'assignement entre deux points
     * @param x : premier point
     * @param y : deuxieme point
     * @param valeur : le cout d'assignement entre deux points
     */
    public void setCoutAssignement(int x, int y, int valeur) {
        coutAssignement[x][y] = valeur;
    }

    /**
     * Retourne la distance entre deux point du cycle
     * @param x : premier point
     * @param y : deuxi�me point
     * @return : la distance entre deux point du cycle
     */
    public int getCycleDistance(int x, int y) {
        return cycleDistance[x][y];
    }

    /**
     * Retourne la distance entre deux point du cycle
     * @param x : premier point
     * @param y : deuxieme point
     * @param valeur : la distance entre deux point du cycle
     */
    public void setCycleDistance(int x, int y, int valeur) {
        cycleDistance[x][y] = valeur;
    }
}

